package com.fifth.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fifth.common.pojo.dto.CommonResult;
import com.fifth.common.pojo.entity.Comment;
import com.fifth.common.pojo.entity.Order;
import com.fifth.common.pojo.entity.PayLog;
import com.fifth.common.pojo.entity.Stock;
import com.fifth.order.config.HttpClient;
import com.fifth.order.feign.CommentFeign;
import com.fifth.order.mapper.OrderMapper;
import com.fifth.order.mapper.PayLogMapper;
import com.fifth.order.mapper.StockMapper;
import com.fifth.order.service.PayLogService;
import com.fifth.order.vo.WebUtils;
import com.github.wxpay.sdk.WXPayUtil;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @作者：刘壬杉
 * @创建时间 2022/9/2 9:23
 **/
@Service
public class PayLogServiceImpl implements PayLogService {

    @Autowired
    private PayLogMapper payLogMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Value("${weixin.appid}")
    private String appId;
    @Value("${weixin.mch_id}")
    private String mchId;
    @Value("${weixin.api_key}")
    private String apiKey;

    //支付宝支付需要的配置
    @Value("${alipay.app_id}")
    private String aliAppId;
    @Value("${alipay.private_key}")
    private String aliPrivateId;
    @Value("${alipay.public_key}")
    private String aliPublicKey;
    @Value("${alipay.getway_url}")
    private String aliGetwayUrl;

    @Resource
    private CommentFeign commentFeign;

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private Redisson redisson;

    @Autowired
    private StockMapper stockMapper;

    /**
     * 校验是否支付成功
     *
     * @param code
     * @return
     */
    @Override
    public CommonResult payStatus(String code) {
        //获取锁对象
        RLock lock = redisson.getLock("pay::" + code);
        try {//Redission上锁
            lock.lock(30, TimeUnit.SECONDS);
            //获取userid
            HttpServletRequest requestToken = WebUtils.getRequest();
            //获取token
            String token = requestToken.getHeader("token");
            //根据token获取userid
            Map userMap = JSON.parseObject(redisTemplate.opsForValue().get(token), Map.class);
            String userid;
            if (userMap != null && userMap.containsKey("user")) {
                JSONObject user = (JSONObject) userMap.get("user");
                userid = user.getString("id");
            } else {
                return new CommonResult(4000, "登录失效,请登录后再购买", null);
            }
            //根据code查询订单信息
            List<Map> maps = orderMapper.selectByCode(code);
            //获取支付类型
            Integer payStatus = (Integer) maps.get(0).get("paysort");
            //获取支付金额
            BigDecimal totalMoney = new BigDecimal("0");
            //获取List<goodsid>
            List<String> goodsids = new ArrayList<>();
            for (Map map1 : maps) {
                BigDecimal money = (BigDecimal) map1.get("totalmoney");
                totalMoney = totalMoney.add(money);
                goodsids.add((String) map1.get("goodsid"));
            }
            if (payStatus == 0) {
                try {//微信支付
                    HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
                    httpClient.setHttps(true);
                    Map<String, String> map = new HashMap<>();
                    map.put("appid", appId);
                    map.put("mch_id", mchId);
                    //商户订单号
                    map.put("out_trade_no", code);
                    map.put("nonce_str", WXPayUtil.generateNonceStr());
                    httpClient.setXmlParam(WXPayUtil.generateSignedXml(map, apiKey));
                    httpClient.post();
                    String content = httpClient.getContent();
                    Map<String, String> xmlToMap = WXPayUtil.xmlToMap(content);
                    //交易成功判断条件： return_code、result_code和trade_state都为SUCCESS
                    if (xmlToMap.get("trade_state").equals("SUCCESS")) {
                        //修改code中对应的商品库存
                        for (Map map1 : maps) {
                            String goodsid = (String) map1.get("goodsid");
                            Integer num = (Integer) map1.get("num");
                            //根据商品id查询对应商品库存
                            QueryWrapper<Stock> queryWrapper1 = new QueryWrapper<>();
                            queryWrapper1.eq("goods_id", goodsid);
                            Stock stockInfo = stockMapper.selectOne(queryWrapper1);
                            //修改商品库存
                            Stock stock = new Stock();
                            stock.setSellNum(stockInfo.getSellNum() + num);
                            stock.setResidue(stockInfo.getResidue() - num);
                            QueryWrapper<Stock> queryWrapper2 = new QueryWrapper<>();
                            queryWrapper2.eq("goods_id", goodsid);
                            stockMapper.update(stock, queryWrapper2);
                        }
                        //根据code修改o_order数据库中的状态
                        Order order = new Order();
                        order.setState(0);
                        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("code", code);
                        orderMapper.update(order, queryWrapper);
                        //将交易信息记录到o_payLog
                        PayLog payLog = new PayLog();
                        payLog.setOrderNo(code);
                        payLog.setTotalFee(totalMoney);
                        payLog.setPaysort(payStatus);
                        payLog.setAttr(xmlToMap.get("attch"));
                        payLog.setTradeState(xmlToMap.get("trade_state"));
                        payLog.setTransactionId(xmlToMap.get("transaction_id"));
                        payLogMapper.insert(payLog);
                        //订单记录添加到用户评论表
                        for (String goodsid : goodsids) {
                            commentFeign.addComment(code, userid, goodsid);
                        }
                        redisTemplate.delete("prefecture");

                        return new CommonResult(2000, "支付成功", null);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return new CommonResult(5000, "暂未支付", null);
            } else {
                try {
                    AlipayClient alipayClient = new DefaultAlipayClient(aliGetwayUrl, aliAppId, aliPrivateId, "json", "utf-8", aliPublicKey, "RSA2");
                    AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
                    JSONObject bizContent = new JSONObject();
                    bizContent.put("out_trade_no", code);
                    request.setBizContent(bizContent.toString());
                    AlipayTradeQueryResponse response = alipayClient.execute(request);
                    String status = response.getTradeStatus();//获取订单的状态
                    //交易状态：WAIT_BUYER_PAY（交易创建，等待买家付款）、
                    // TRADE_CLOSED（未付款交易超时关闭，或支付完成后全额退款）、
                    // TRADE_SUCCESS（交易支付成功）、
                    // TRADE_FINISHED（交易结束，不可退款)
                    if (status != null && status.equals("TRADE_SUCCESS")) {
                        //修改code中对应的商品库存
                        for (Map map1 : maps) {
                            String goodsid = (String) map1.get("goodsid");
                            Integer num = (Integer) map1.get("num");
                            //根据商品id查询对应商品库存
                            QueryWrapper<Stock> queryWrapper1 = new QueryWrapper<>();
                            queryWrapper1.eq("goods_id", goodsid);
                            Stock stockInfo = stockMapper.selectOne(queryWrapper1);
                            //修改商品库存
                            Stock stock = new Stock();
                            stock.setSellNum(stockInfo.getSellNum() + num);
                            stock.setResidue(stockInfo.getResidue() - num);
                            QueryWrapper<Stock> queryWrapper2 = new QueryWrapper<>();
                            queryWrapper2.eq("goods_id", goodsid);
                            stockMapper.update(stock, queryWrapper2);
                        }
                        //更新订单状态
                        Order order = new Order();
                        order.setState(0);
                        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("code", code);
                        orderMapper.update(order, queryWrapper);
                        //添加支付日志
                        PayLog payLog = new PayLog();
                        payLog.setOrderNo(code);
                        payLog.setTotalFee(totalMoney);
                        payLog.setPaysort(payStatus);
                        payLog.setAttr(response.getExtInfos());
                        payLog.setTradeState(status);
                        payLog.setTransactionId(response.getTradeNo());
                        //查询交易记录表中是否有该code
                        QueryWrapper<PayLog> queryWrapper1 = new QueryWrapper<>();
                        queryWrapper1.eq("order_no", code);
                        PayLog payLog1 = payLogMapper.selectOne(queryWrapper1);
                        if (payLog1 == null) {
                            payLogMapper.insert(payLog);
                        } else {
                            return new CommonResult(4000, "该订单已有交易记录", null);
                        }
                        //订单记录添加到用户评论表
                        for (String goodsid : goodsids) {
                            commentFeign.addComment(code, userid, goodsid);
                        }
                        redisTemplate.delete("prefecture");
                        return new CommonResult(2000, "支付成功", null);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return new CommonResult(5000, "暂未支付", null);
            }
        } finally {
            //释放锁
            lock.unlock();
        }

    }
}
